package qc.module.ehs.api.controller;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import qc.common.core.constants.QCAuthConstant;
import qc.common.core.exception.QCPromptException;
import qc.common.core.utils.DateUtil;
import qc.module.ehs.dto.hazardidentity.*;
import qc.module.ehs.service.EhsHazardIdentifyService;
import qc.module.platform.dto.uac.UacUserInfoDto;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * HazardIdentifyController
 * 危险源辨识
 *
 * @author QuCheng Tech
 * @create 2024/11/5
 */
@RestController
@RequestMapping("/hazardidentify")
public class HazardIdentifyController {

    @Autowired
    private EhsHazardIdentifyService service;

    @Autowired
    HttpServletRequest request;

    @Autowired
    private RestTemplatePlatform restTemplatePlatform;

    /**
     * 查询危险源辨识记录
     *
     * @param condition 查询条件
     * @return HazardIdentifyQueryResultDto
     * @author QuCheng Tech
     * @description 1.用于查询指定时间段内的危险源辨识记录；
     * 2.查询当前用户有权限的单元指定时间段内的辨识记录；
     * 3.返回结果按单元进行显示，每个单元显示所有辨识记录（可能会有多个时间的辨识记录），单元有子级单元时按单元层级关系显示；
     * @since 2024/11/5
     */
    @RequestMapping(value = "/query", method = {RequestMethod.POST})
    public HazardIdentifyQueryResultDto query(@RequestBody HazardIdentifyQueryConditionDto condition) throws QCPromptException {
        return service.query(condition);
    }

    /**
     * 获取指定单元的危险源辨识记录
     * 获取指定单元指定时间段内的危险源辨识记录，单元ID必须指定；不管确认状态；
     *
     * @param condition 查询条件
     * @return HazardIdentifyQueryResultDto
     * @throws QCPromptException
     * @author QuCheng Tech
     * @since 2024/11/5
     */
    @RequestMapping(value = "/unit", method = {RequestMethod.POST})
    public List<HazardIdentifyInfoDto> queryByUnit(@RequestBody HazardIdentifyQueryConditionDto condition) throws QCPromptException {
        if (condition == null)
            throw new QCPromptException("查询条件不能为空");
        if (StringUtils.isBlank(condition.getUnitid()))
            throw new QCPromptException("单元ID必须指定");
        if (StringUtils.isBlank(condition.getBegintm()))
            throw new QCPromptException("查询起始时间不能为空");
        if (StringUtils.isBlank(condition.getEndtm()))
            throw new QCPromptException("查询截止时间不能为空");
        //查询时间处理
        Date beginDate = null;
        Date endDate = null;
        if (StringUtils.isNotBlank(condition.getBegintm())) {
            try {
                beginDate = DateUtil.parseDate(condition.getBegintm());
            } catch (Exception e) {
                // 时间转换错误，抛出自定义异常
                throw new QCPromptException("查询条件中的开始日期转换错误");
            }
        }
        if (StringUtils.isNotBlank(condition.getEndtm())) {
            try {
                endDate = DateUtil.parseDate(condition.getEndtm());
            } catch (Exception e) {
                // 时间转换错误，抛出自定义异常
                throw new QCPromptException("查询条件中的截止日期转换错误");
            }
        }
        if (beginDate == null)
            throw new QCPromptException("查询起始时间无效");
        if (endDate == null)
            throw new QCPromptException("查询截止时间无效");
        if (beginDate.after(endDate))
            throw new QCPromptException("查询起始时间不能大于截止时间");

        return service.queryByUnit(condition.getUnitid(), beginDate, endDate);
    }

    /**
     * 指定单元全面辨识危险源
     *
     * @param unitid 单元ID
     * @return QueryOneUnitHazardResultDto
     * @author QuCheng Tech
     * @description 使用单元分类关联的危险源清单作为该单元的危险源清单。需要处理以下几种情况：
     * 1.原有记录无该危险源，现有该危险源时：新增危险源辨识记录、新增危险源信息；
     * 2.原有记录有该危险源，现有该危险源时：新增危险源辨识记录、修改危险源信息；
     * 3.原有记录有该危险源，现无该危险源时：新增危险源辨识记录、修改危险源信息；辨识结果为“不存在”。
     * @since 2024/11/5
     */
    @RequestMapping(value = "/overall", method = {RequestMethod.GET, RequestMethod.POST})
    public HazardIdentifyOperateResultDto identificationOverAllByParam(@RequestParam String unitid) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        // 获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (userInfo == null)
            throw new QCPromptException("根据用户凭据获取不到有效的用户信息，可能用户凭据已失效");
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0x0)
            throw new QCPromptException("根据用户凭据获取到的用户ID无效");

        //2.根据部门ids获取当前用户所属组织，用户可能在多个组织中不能确定本次操作的是哪个组织
        //修改为组织代码由前端传入，此处不再需要根据用户进行获取；
        //String projectCode = userInfo.getProject();
        //EhsOrgDto org = orgController.getUserOrgByParam(projectCode);
        //if (Objects.isNull(org)) throw new QCPromptException("当前用户无有效组织信息");
        //String orgCode = org.getOrgcode();

        return service.identificationOverAll(unitid, userInfo.getId().intValue(), userInfo.getName());
    }

    /**
     * 指定单元全面辨识危险源
     *
     * @param unitid 单元ID
     * @return QueryOneUnitHazardResultDto
     * @author QuCheng Tech
     * @description 使用单元分类关联的危险源清单作为该单元的危险源清单。需要处理以下几种情况：
     * 1.原有记录无该危险源，现有该危险源时：新增危险源辨识记录、新增危险源信息；
     * 2.原有记录有该危险源，现有该危险源时：新增危险源辨识记录、修改危险源信息；
     * 3.原有记录有该危险源，现无该危险源时：新增危险源辨识记录、修改危险源信息；辨识结果为“不存在”。
     * @since 2024/11/5
     */
    @RequestMapping(value = "/overall/{unitid}", method = {RequestMethod.GET, RequestMethod.POST})
    public HazardIdentifyOperateResultDto identificationOverAllByPath(@PathVariable String unitid) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        // 获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (userInfo == null)
            throw new QCPromptException("根据用户凭据获取不到有效的用户信息，可能用户凭据已失效");
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0x0)
            throw new QCPromptException("根据用户凭据获取到的用户ID无效");

        //2.根据部门ids获取当前用户所属组织，用户可能在多个组织中不能确定本次操作的是哪个组织
        //修改为组织代码由前端传入，此处不再需要根据用户进行获取；
        //String projectCode = userInfo.getProject();
        //EhsOrgDto org = orgController.getUserOrgByParam(projectCode);
        //if (Objects.isNull(org)) throw new QCPromptException("当前用户无有效组织信息");
        //String orgCode = org.getOrgcode();

        return service.identificationOverAll(unitid, userInfo.getId().intValue(), userInfo.getName());
    }

    /**
     * 新增危险源辨识记录
     * 新增1条危险源辨识记录；可以用于新增危险源辨识和对已有的危险源进行重新辨识操作；
     *
     * @param addDto 新增对象DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @since 2024/11/6
     */
    @RequestMapping(value = "/add", method = {RequestMethod.POST})
    public HazardIdentifyOperateResultDto add(@RequestBody HazardIdentifyAddDto addDto) throws QCPromptException, ParseException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        // 获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (userInfo == null)
            throw new QCPromptException("根据用户凭据获取不到有效的用户信息，可能用户凭据已失效");
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0x0)
            throw new QCPromptException("根据用户凭据获取到的用户ID无效");

        return service.add(addDto, userInfo.getId().intValue(), userInfo.getName());
    }

    /**
     * 辨识已存在的危险源无变化
     *
     * @param id 危险源ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @description 用于对已有的危险源信息确认无任何变化。点击该按钮弹出确认提示，确认后在危险源辨识记录表中插入一条最新的记录，危险源的信息与危险源的最新数据一致。
     * @since 2024/11/6
     */
    @RequestMapping(value = "/nochange", method = {RequestMethod.GET, RequestMethod.POST})
    public HazardIdentifyOperateResultDto noChangeByParam(@RequestParam String id) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        //获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (userInfo == null)
            throw new QCPromptException("根据用户凭据获取不到有效的用户信息，可能用户凭据已失效");
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0x0)
            throw new QCPromptException("根据用户凭据获取到的用户ID无效");

        return service.noChange(id, userInfo.getId().intValue(), userInfo.getName());
    }

    /**
     * 辨识已存在的危险源无变化
     *
     * @param id 危险源ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @description 用于对已有的危险源信息确认无任何变化。点击该按钮弹出确认提示，确认后在危险源辨识记录表中插入一条最新的记录，危险源的信息与危险源的最新数据一致。
     * @since 2024/11/6
     */
    @RequestMapping(value = "/nochange/{id}", method = {RequestMethod.GET, RequestMethod.POST})
    public HazardIdentifyOperateResultDto noChangeByPath(@PathVariable String id) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        //获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (userInfo == null)
            throw new QCPromptException("根据用户凭据获取不到有效的用户信息，可能用户凭据已失效");
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0x0)
            throw new QCPromptException("根据用户凭据获取到的用户ID无效");

        return service.noChange(id, userInfo.getId().intValue(), userInfo.getName());
    }

    /**
     * 获取指定辨识记录
     *
     * @param id 危险源辨识记录ID
     * @return HazardIdentifyInfoDto
     * @author QuCheng Tech
     * @since 2024/11/8
     */
    @GetMapping("/get")
    public HazardIdentifyInfoDto getByParam(@RequestParam String id) {
        return service.get(id);
    }

    /**
     * 获取指定辨识记录
     *
     * @param id 危险源辨识记录ID
     * @return HazardIdentifyInfoDto
     * @author QuCheng Tech
     * @since 2024/11/8
     */
    @GetMapping("/get/{id}")
    public HazardIdentifyInfoDto getByPath(@PathVariable String id) {
        return service.get(id);
    }

    /**
     * 修改危险源辨识记录
     *
     * @param dto 修改对象DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @description 对危险源辨识记录进行修改；需要判断记录是否确认，确认后的危险源辨识记录不能修改；
     * @since 2024/11/6
     */
    @RequestMapping(value = "/update", method = {RequestMethod.POST, RequestMethod.PUT})
    public HazardIdentifyOperateResultDto update(@RequestBody HazardIdentifyInfoDto dto) throws QCPromptException {
        return service.update(dto);
    }

    /**
     * 删除危险源辨识记录
     *
     * @param id 辨识ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @description 对危险源辨识记录进行删除；需要判断记录是否确认，确认后的危险源辨识记录不能删除；
     * @since 2024/11/6
     */
    @DeleteMapping("/delete")
    public HazardIdentifyOperateResultDto deleteByParam(@RequestParam String id) {
        return service.delete(id);
    }

    /**
     * 删除危险源辨识记录
     *
     * @param id 辨识ID
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @description 对危险源辨识记录进行删除；需要判断记录是否确认，确认后的危险源辨识记录不能删除；
     * @since 2024/11/6
     */
    @DeleteMapping("/delete/{id}")
    public HazardIdentifyOperateResultDto deleteByPath(@PathVariable String id) {
        return service.delete(id);
    }

    /**
     * 确认辨识的危险源记录
     *
     * @param dto 危险源辨识记录确认DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCheng Tech
     * @description 对指定的危险源辨识记录进行确认；确认后需要根据确认的结果对危险源信息表数据进行更新；确认操作可以多次进行，已防止误操作时对已有数据进行修改；
     * 如传入危险源ID表示确认辨识记录对应的危险源ID为传入值，如未传入危险源ID先根据辨识记录新增1个危险源信息再进行关联；
     * 注意：需要根据危险源辨识记录表中的已有危险源ID和传入的危险源ID进行判断，可能存在本次设置的危险源ID与上次设置的危险源ID不一致的情况，会导致危险源信息表中的危险源信息错误；
     * @since 2024/11/6
     */
    @RequestMapping(value = "/confirm", method = {RequestMethod.POST})
    public HazardIdentifyConfirmResultDto confirm(@RequestBody HazardIdentifyConfirmDto dto) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        //获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (userInfo == null)
            throw new QCPromptException("根据用户凭据获取不到有效的用户信息，可能用户凭据已失效");
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0x0)
            throw new QCPromptException("根据用户凭据获取到的用户ID无效");

        return service.confirm(dto, userInfo.getId().intValue(), userInfo.getName());
    }

    /**
     * 查询危险源辨识记录确认
     * 用于对危险源辨识记录进行确认操作时的查询条件；可以用于查询辨识记录和查询的上报隐患；
     * 查询结果按照单元名称、类别名称、项目名称、危险源名称升序，再按照辨识时间降序；
     *
     * @param condition 查询条件DTO
     * @return List<HazardIdentifyInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/6
     */
    @RequestMapping(value = "/queryconfirm", method = {RequestMethod.GET, RequestMethod.POST})
    public List<HazardIdentifyInfoDto> queryConfirm(@RequestBody HazardIdentifyConfirmQueryConditionDto condition) throws QCPromptException {
        return service.queryConfirm(condition);
    }

    /**
     * 查询我的危险源辨识记录
     * <p>
     * 用于查询指定时间段内单元用户填报的危险源辨识记录；
     * 不管用户的单元权限，只管填报人是当前用户即可；不管辨识记录是否确认；
     *
     * @param condition 查询条件
     * @return List<HazardIdentifyInfoDto>
     * @author QuCheng Tech
     * @since 2024/12/3
     */
    @RequestMapping(value = "my", method = {RequestMethod.POST})
    public List<HazardIdentifyInfoDto> queryMy(@RequestBody HazardIdentifyQueryConditionDto condition) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        //获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);
        if (userInfo == null)
            throw new QCPromptException("根据用户凭据获取不到有效的用户信息，可能用户凭据已失效");
        if (userInfo.getId() == null || userInfo.getId().intValue() <= 0x0)
            throw new QCPromptException("根据用户凭据获取到的用户ID无效");

        return service.queryMy(condition, userInfo.getId().intValue());
    }
}
